Installation¶
In [ ]:
Copied!
!pip install hyperopt
!pip install hyperopt
Sample Strategy¶
In [1]:
Copied!
# import talib.abstract as ta
from lettrade import DataFeed, Strategy, crossover, crossunder
from lettrade.exchange.backtest import ForexBackTestAccount, let_backtest
from lettrade.indicator.vendor.qtpylib import inject_indicators
inject_indicators()
class SmaCross(Strategy):
ema1_period = 9
ema2_period = 21
def indicators(self, df: DataFeed):
# df["ema1"] = ta.EMA(df, timeperiod=self.ema1_period)
# df["ema2"] = ta.EMA(df, timeperiod=self.ema2_period)
df["ema1"] = df.close.ema(window=self.ema1_period)
df["ema2"] = df.close.ema(window=self.ema2_period)
df["signal_ema_crossover"] = crossover(df.ema1, df.ema2)
df["signal_ema_crossunder"] = crossunder(df.ema1, df.ema2)
def next(self, df: DataFeed):
if len(self.orders) > 0 or len(self.trades) > 0:
return
if df.l.signal_ema_crossover[-1]:
price = df.l.close[-1]
self.buy(size=0.1, sl=price - 0.001, tp=price + 0.001)
elif df.l.signal_ema_crossunder[-1]:
price = df.l.close[-1]
self.sell(size=0.1, sl=price + 0.001, tp=price - 0.001)
lt = let_backtest(
strategy=SmaCross,
datas="example/data/data/EURUSD_5m_0_10000.csv",
account=ForexBackTestAccount,
# plotter=None,
)
# import talib.abstract as ta
from lettrade import DataFeed, Strategy, crossover, crossunder
from lettrade.exchange.backtest import ForexBackTestAccount, let_backtest
from lettrade.indicator.vendor.qtpylib import inject_indicators
inject_indicators()
class SmaCross(Strategy):
ema1_period = 9
ema2_period = 21
def indicators(self, df: DataFeed):
# df["ema1"] = ta.EMA(df, timeperiod=self.ema1_period)
# df["ema2"] = ta.EMA(df, timeperiod=self.ema2_period)
df["ema1"] = df.close.ema(window=self.ema1_period)
df["ema2"] = df.close.ema(window=self.ema2_period)
df["signal_ema_crossover"] = crossover(df.ema1, df.ema2)
df["signal_ema_crossunder"] = crossunder(df.ema1, df.ema2)
def next(self, df: DataFeed):
if len(self.orders) > 0 or len(self.trades) > 0:
return
if df.l.signal_ema_crossover[-1]:
price = df.l.close[-1]
self.buy(size=0.1, sl=price - 0.001, tp=price + 0.001)
elif df.l.signal_ema_crossunder[-1]:
price = df.l.close[-1]
self.sell(size=0.1, sl=price + 0.001, tp=price - 0.001)
lt = let_backtest(
strategy=SmaCross,
datas="example/data/data/EURUSD_5m_0_10000.csv",
account=ForexBackTestAccount,
# plotter=None,
)
Optimize¶
In [2]:
Copied!
# define a search space
from hyperopt import fmin, tpe, space_eval, Trials
from hyperopt import hp
lettrade_model = lt.optimize_model(fork_data=True)
def train_model(params):
# Params
params = [
("ema1_period", params["ema1_period"]),
("ema2_period", params["ema2_period"]),
]
# Model
result = lettrade_model(params)
# Score
return -result["equity"]
# Hyperopt
search_space = {
"ema1_period": hp.uniform("ema1_period", 5, 25),
"ema2_period": hp.uniform("ema2_period", 10, 50),
}
trials = Trials()
best_params = fmin(
train_model,
search_space,
algo=tpe.suggest,
max_evals=1_000,
trials=trials,
)
# define a search space
from hyperopt import fmin, tpe, space_eval, Trials
from hyperopt import hp
lettrade_model = lt.optimize_model(fork_data=True)
def train_model(params):
# Params
params = [
("ema1_period", params["ema1_period"]),
("ema2_period", params["ema2_period"]),
]
# Model
result = lettrade_model(params)
# Score
return -result["equity"]
# Hyperopt
search_space = {
"ema1_period": hp.uniform("ema1_period", 5, 25),
"ema2_period": hp.uniform("ema2_period", 10, 50),
}
trials = Trials()
best_params = fmin(
train_model,
search_space,
algo=tpe.suggest,
max_evals=1_000,
trials=trials,
)
100%|██████████| 1000/1000 [03:03<00:00, 5.46trial/s, best loss: -1207.68]
In [3]:
Copied!
hyperparams = space_eval(search_space, best_params)
print(best_params)
print(hyperparams)
trials
hyperparams = space_eval(search_space, best_params)
print(best_params)
print(hyperparams)
trials
{'ema1_period': 11.053178614989243, 'ema2_period': 10.03623279848111}
{'ema1_period': 11.053178614989243, 'ema2_period': 10.03623279848111}
Out[3]:
<hyperopt.base.Trials at 0x7e2cc49564e0>
Init Plotly environment¶
In [4]:
Copied!
import plotly.io as pio
pio.renderers.default = "notebook"
pio.templates.default = "plotly_dark"
import plotly.io as pio
pio.renderers.default = "notebook"
pio.templates.default = "plotly_dark"
In [5]:
Copied!
import pandas as pd
import numpy as np
def unpack(x):
if x:
return x[0]
return np.nan
# We'll first turn each trial into a series and then stack those series together as a dataframe.
df = pd.DataFrame([pd.Series(t["misc"]["vals"]).apply(unpack) for t in trials])
# Then we'll add other relevant bits of information to the correct rows and perform a couple of
# mappings for convenience
df["loss"] = [t["result"]["loss"] for t in trials]
df["trial_number"] = df.index
df["win"] = -df["loss"]
df
import pandas as pd
import numpy as np
def unpack(x):
if x:
return x[0]
return np.nan
# We'll first turn each trial into a series and then stack those series together as a dataframe.
df = pd.DataFrame([pd.Series(t["misc"]["vals"]).apply(unpack) for t in trials])
# Then we'll add other relevant bits of information to the correct rows and perform a couple of
# mappings for convenience
df["loss"] = [t["result"]["loss"] for t in trials]
df["trial_number"] = df.index
df["win"] = -df["loss"]
df
Out[5]:
| ema1_period | ema2_period | loss | trial_number | win | |
|---|---|---|---|---|---|
| 0 | 23.011308 | 32.392422 | -874.78 | 0 | 874.78 |
| 1 | 12.385649 | 39.959152 | -941.18 | 1 | 941.18 |
| 2 | 21.489922 | 13.589022 | -1148.68 | 2 | 1148.68 |
| 3 | 24.811106 | 19.719090 | -1029.18 | 3 | 1029.18 |
| 4 | 24.391799 | 21.758360 | -1048.48 | 4 | 1048.48 |
| ... | ... | ... | ... | ... | ... |
| 995 | 12.980240 | 10.686655 | -1163.58 | 995 | 1163.58 |
| 996 | 23.522512 | 13.970659 | -1070.48 | 996 | 1070.48 |
| 997 | 14.089796 | 10.051155 | -1163.78 | 997 | 1163.78 |
| 998 | 13.415534 | 11.662155 | -1140.18 | 998 | 1140.18 |
| 999 | 11.819916 | 12.762065 | -829.68 | 999 | 829.68 |
1000 rows × 5 columns
Type 1¶
In [6]:
Copied!
from plotly import express as px
fig = px.scatter(df, x="trial_number", y="win")
fig.show()
from plotly import express as px
fig = px.scatter(df, x="trial_number", y="win")
fig.show()
Type 2¶
In [7]:
Copied!
import plotly.express as px
fig = px.density_contour(
df,
x="ema1_period",
y="ema2_period",
z="win",
histfunc="max",
)
fig.update_traces(contours_coloring="fill", contours_showlabels=True)
fig.show()
import plotly.express as px
fig = px.density_contour(
df,
x="ema1_period",
y="ema2_period",
z="win",
histfunc="max",
)
fig.update_traces(contours_coloring="fill", contours_showlabels=True)
fig.show()
Type 3¶
In [8]:
Copied!
import plotly.express as px
fig = px.density_heatmap(
df,
x="ema1_period",
y="ema2_period",
z="win",
nbinsx=20,
nbinsy=40,
histfunc="max",
color_continuous_scale="Viridis",
)
fig.show()
import plotly.express as px
fig = px.density_heatmap(
df,
x="ema1_period",
y="ema2_period",
z="win",
nbinsx=20,
nbinsy=40,
histfunc="max",
color_continuous_scale="Viridis",
)
fig.show()